/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.ctu.labiras.testador;

import br.ctu.labiras.aco.Aco;
import br.ctu.labiras.aco.Formiga;
import br.ctu.labiras.aco.Parametros;
import br.ctu.labiras.utils.ArquivoUtils;

import java.io.File;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;

/**
 *
 * @author THIAGO
 */
public class EstrategiaAco extends EstrategiaBase{
    private Aco aco;
    private Parametros parametros;
    private int[] composicao;        
    
    public EstrategiaAco() {        
        this.configuraParametros();
    }
        
    @Override
    protected final void configuraParametros() {
        try{
            parametros = new Parametros();
            DocumentBuilderFactory xml = DocumentBuilderFactory.newInstance();
            Document doc = xml.newDocumentBuilder().parse(new File("src/utils/config.xml"));                        
            
            float alpha = Float.parseFloat(doc.getElementsByTagName("alpha").item(0).getTextContent());
            parametros.setAlpha(alpha);
            float beta = Float.parseFloat(doc.getElementsByTagName("beta").item(0).getTextContent());
            parametros.setBeta(beta);
            double rho = Double.parseDouble(doc.getElementsByTagName("rho").item(0).getTextContent());
            parametros.setRho(rho);
            double q = Double.parseDouble(doc.getElementsByTagName("q").item(0).getTextContent());
            parametros.setQ(q);
            boolean usarHeuristica = Boolean.parseBoolean(doc.getElementsByTagName("heuristica").item(0).getTextContent());
            parametros.setUsarHeuristica(usarHeuristica);
            int numAnts = Integer.parseInt(doc.getElementsByTagName("ants").item(0).getTextContent());            
            parametros.setNumAnts(numAnts);
            int numIter = Integer.parseInt(doc.getElementsByTagName("iteracoes").item(0).getTextContent());            
            parametros.setNumIter(numIter);
            double c = Double.parseDouble(doc.getElementsByTagName("c").item(0).getTextContent());
            parametros.setC(c);
            int numCelulas = Integer.parseInt(doc.getElementsByTagName("num_celulas").item(0).getTextContent());            
            parametros.setNumCelulas(numCelulas);
            int numTransicoes = Integer.parseInt(doc.getElementsByTagName("num_transicoes").item(0).getTextContent());            
            parametros.setNumTransicoes(numTransicoes);               
            
            path = doc.getElementsByTagName("Path").item(0).getTextContent();
            max_gera = Integer.parseInt(doc.getElementsByTagName("Max_gera").item(0).getTextContent());
            max_fit = Integer.parseInt(doc.getElementsByTagName("Max_fit").item(0).getTextContent());
            max_interacoes = Integer.parseInt(doc.getElementsByTagName("Max_interacoes").item(0).getTextContent());
            QE = doc.getElementsByTagName("Qtde").getLength();			
            elementos = new int[QE][2]; //coluna 1: qtde; coluna 2: codigo do elemento
            repeticao = Integer.parseInt(doc.getElementsByTagName("Repeticao").item(0).getTextContent());
            
            for (int i = 0; i < doc.getElementsByTagName("Qtde").getLength(); i++) {
                    elementos[i][0] = Integer.parseInt(doc.getElementsByTagName("Qtde").item(i).getTextContent());
                    L += elementos[i][0];
                    elementos[i][1] = Integer.parseInt(doc.getElementsByTagName("Codigo").item(i).getTextContent());
            }
            qLinhaColuna = (int)Math.sqrt(L);
            
            //Obtem os objetivos com sua respectiva pontuacao
            for (int i = 0; i <  doc.getElementsByTagName("Objetivo").getLength(); i++)
                    objetivos.put(doc.getElementsByTagName("Objetivo").item(i).getAttributes().getNamedItem("nome").getNodeValue(),
                                    Double.parseDouble(doc.getElementsByTagName("Objetivo").item(i).getAttributes().getNamedItem("peso").getNodeValue()));

            //Obtem as medidas de avaliacao
            for (int i = 0; i <  doc.getElementsByTagName("Medida").getLength(); i++) {
                    FuncaoAvaliacao avaliacao = new FuncaoAvaliacao();
                    avaliacao.setElemento(Integer.parseInt(doc.getElementsByTagName("Elemento").item(i).getTextContent()));
                    avaliacao.setAcao(doc.getElementsByTagName("Acao").item(i).getTextContent());

                    Enumeration<String> e = objetivos.keys();
                    while(e.hasMoreElements())
                    {
                            String objetivo = (String)e.nextElement();
                            avaliacao.pontuacao.put(objetivo, Double.parseDouble(doc.getElementsByTagName(objetivo).item(i).getTextContent()));
                    }
                    funcaoAvaliacao.add(avaliacao);
            }
            arquivo = new ArquivoUtils(path);
            arquivo.iniciaImpressao();
            
            aco = new Aco(parametros);
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    
//    public static void main(String [] args) {
//        EstrategiaAco estrategia = new EstrategiaAco();
//        //estrategia.geraPopulacaoInicial();
//        estrategia.aco.executar();
//    }
    
    protected Populacao obtemPopulacao() {
        Populacao populacao = null;        
        
        aco.checarSolucoes();
        aco.atualizarFeromonio();
        aco.resetarFormigas();
        populacao = sucessor();       
        
        //Acabou o teste        
        if (populacao == null) {
                System.out.println("Melhores indivíduos = " + melhoresIndividuos);
                arquivo.imprime3(populacao, melhoresIndividuos);
        }
                
        System.out.println("Qtde de novos individuos " + populacao.getIndividuo().size());
        
        if (populacao.getIndividuo().get(0).getHistoria() != null)
        	System.out.println("Tem historia");
        return populacao;
    }
    
    /**
    * @author raquel silveira
    * @version 1.0 
    * metodo que gera a populacao inicial de forma randomica (de acordo com a qtde de salas limpas, sujeira, obstaculos, lixeira e tomada)
    * @return populacao inicial
    * */
    @Override
    protected Populacao geraPopulacaoInicial() {
        Populacao populacaoInicial = new Populacao();			
        
        aco.construirSolucoes();        
        Individuo[] individuos = aco.getFormigas();
        int numIndividuos = individuos.length;
        
        try {
            for (int j = 0; j < numIndividuos; j++) {                
                populacaoInicial.getIndividuo().add(individuos[j]);
            }
            //System.out.println(populacaoInicial.getIndividuo());

            return populacaoInicial;
        } catch (Exception ex) {
            Logger.getLogger(EstrategiaAco.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        return null;
    }

    protected Populacao sucessor() {
        Populacao populacao = new Populacao();			        
        
        aco.construirSolucoes();   
        Individuo[] individuos = aco.getFormigas();
        int numIndividuos = individuos.length;

        try {
            for (int j = 0; j < numIndividuos; j++) {
                individuos[j].listaHistorias = null;
                individuos[j].setHistoria(null);
                individuos[j].setSelecionado(false);
                populacao.getIndividuo().add(individuos[j].clone());                
            }
            return populacao;
        } catch (Exception ex) {
            Logger.getLogger(EstrategiaAco.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    @Override
    protected Populacao obtemPopulacao(Populacao populacaoAnalisada) {
        return obtemPopulacao();
    }
    
//    public static void main(String[] args) {
//        EstrategiaAco estrategia = new EstrategiaAco();
//        estrategia.aco.executar();
//    }
}
